package com.itjeffrey.autocode.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itjeffrey.autocode.bo.ResInfoTbBO;
import com.itjeffrey.autocode.bo.req.ChangeAuthBO;
import com.itjeffrey.autocode.bo.req.ChangeAuthResBO;
import com.itjeffrey.autocode.bo.req.IsEnableBO;
import com.itjeffrey.autocode.bo.resp.AuthrizeResourceBO;
import com.itjeffrey.autocode.common.PageResult;
import com.itjeffrey.autocode.common.Result;
import com.itjeffrey.autocode.constant.SysConstant;
import com.itjeffrey.autocode.entity.ResInfoTbEntity;
import com.itjeffrey.autocode.entity.RoleInfoTbEntity;
import com.itjeffrey.autocode.enums.ExceptionEnum;
import com.itjeffrey.autocode.exception.ACException;
import com.itjeffrey.autocode.mapper.ResInfoTbMapper;
import com.itjeffrey.autocode.mapper.RoleInfoTbMapper;
import com.itjeffrey.autocode.service.ResInfoTbService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itjeffrey.autocode.util.BeanOprUtils;
import com.itjeffrey.autocode.util.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 服务实现类
 *
 * @author: admin
 * @date: 2021-03-28 12:35:25
 */
@Service
public class ResInfoTbServiceImpl extends ServiceImpl<ResInfoTbMapper, ResInfoTbEntity> implements ResInfoTbService {

    @Resource
    private ResInfoTbMapper resInfoTbMapper;

    @Resource
    private RoleInfoTbMapper roleInfoTbMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result add(ResInfoTbBO resInfoTbBO) {
        ResInfoTbEntity resInfoTbEntity = new ResInfoTbEntity();
        BeanUtils.copyProperties(resInfoTbBO, resInfoTbEntity);
        resInfoTbEntity.setCreateTime(DateUtil.getCurTime());
        resInfoTbEntity.setEnabled(true);
        resInfoTbMapper.insert(resInfoTbEntity);
        //角色资源中间表入库admin角色关联该资源
        LambdaQueryWrapper<RoleInfoTbEntity> lambda = new QueryWrapper<RoleInfoTbEntity>().lambda();
        lambda.eq(RoleInfoTbEntity::getRoleName, "admin");
        RoleInfoTbEntity roleInfoTbEntity = roleInfoTbMapper.selectOne(lambda);
        Integer adminRoleId = roleInfoTbEntity.getRoleId();
        resInfoTbMapper.insertAdminRoleRes(adminRoleId, resInfoTbEntity.getResId());
        return Result.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result mod(ResInfoTbBO resInfoTbBO) {
        ResInfoTbEntity resInfoTbEntity = new ResInfoTbEntity();
        resInfoTbEntity.setResDesc(resInfoTbBO.getResDesc());
        resInfoTbEntity.setEnabled(true);
        resInfoTbEntity.setUpdateTime(DateUtil.getCurTime());
        resInfoTbMapper.update(resInfoTbEntity,
                new QueryWrapper<ResInfoTbEntity>().lambda().eq(ResInfoTbEntity::getResName,
                        resInfoTbBO.getResName()));
        return Result.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result delete(Integer id) {
        resInfoTbMapper.deleteById(id);
        //删除角色资源关联表信息
        resInfoTbMapper.deleteRoleResInfosByResId(id);
        return Result.ok();
    }

    @Override
    public Result queryList(ResInfoTbBO resInfoTbBO) {
        if (resInfoTbBO.getCurPage() == null || resInfoTbBO.getSize() == null) {
            return Result.ok(resInfoTbMapper.selectList(new QueryWrapper<>()));
        }
        PageResult<ResInfoTbBO> pageResult =
                new PageResult<ResInfoTbBO>().setCurPageAndSize(resInfoTbBO.calCurPage());
        LambdaQueryWrapper<ResInfoTbEntity> queryWrapper =
                new QueryWrapper<ResInfoTbEntity>().lambda();
        queryWrapper.like(StringUtils.isNotBlank(resInfoTbBO.getResName()), ResInfoTbEntity::getResName,
                resInfoTbBO.getResName());
        queryWrapper.like(StringUtils.isNotBlank(resInfoTbBO.getResUrl()), ResInfoTbEntity::getResUrl,
                resInfoTbBO.getResUrl());
        queryWrapper.eq(StringUtils.isNotBlank(resInfoTbBO.getResType()), ResInfoTbEntity::getResType,
                resInfoTbBO.getResType());
        pageResult.setTotals(resInfoTbMapper.selectCount(queryWrapper));
        queryWrapper.last(SysConstant.DB_KEYWORD_LIMIT + resInfoTbBO.getCurPage() + SysConstant.SPECIAL_CHAR_3
                + resInfoTbBO.getSize());
        queryWrapper.orderByDesc(ResInfoTbEntity::getResId);
        pageResult.setData(BeanOprUtils.copyListProperties(resInfoTbMapper.selectList(queryWrapper), ResInfoTbBO::new));
        return Result.ok(pageResult);
    }

    /**
     * 根据角色ID查询已授权的资源信息
     *
     * @param roleId
     * @return
     */
    @Override
    @Cacheable(value = "AutoCode::ResInfo", keyGenerator = "keyGenerator", unless = "#result==null")
    public List<ResInfoTbEntity> queryResInfosByRoleId(Integer roleId, String resType) {
        return resInfoTbMapper.queryResInfosByRoleId(roleId, resType);
    }

    @Override
    public Result queryAuthrizeResource(ResInfoTbBO resInfoTbBO) {
        AuthrizeResourceBO authrizeResourceBO = new AuthrizeResourceBO();
        if (resInfoTbBO.getRoleId() == null) {
            throw new ACException(ExceptionEnum.PARAM_EXISTS_NULL);
        }
        //已授权资源
        List<ResInfoTbEntity> resInfoTbEntities = this.queryResInfosByRoleId(resInfoTbBO.getRoleId(), null);
        authrizeResourceBO.setHasAuthrizeResources(BeanOprUtils.copyListProperties(resInfoTbEntities, ResInfoTbBO::new));
        //未授权资源
        List<ResInfoTbEntity> resInfoTbBOS = this.queryHasNotAuthrizeResources(resInfoTbBO.getRoleId());
        authrizeResourceBO.setHasNotAuthrizeResources(BeanOprUtils.copyListProperties(resInfoTbBOS, ResInfoTbBO::new));
        return Result.ok(authrizeResourceBO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result changeAuth(ChangeAuthBO changeAuthBO) {
        boolean isAuth = changeAuthBO.getIsAuth();
        //解析需要变更的资源列表
        List<ChangeAuthResBO> changeAuthList = changeAuthBO.getChangeAuthList();
//        List<String> labels = changeAuthList.stream().map(t -> t.getLabel()).collect(Collectors.toList());

        /**
         * 授权：新增角色资源数据
         * 取消授权：删除对应角色资源数据
         */
        if (isAuth) {
//            resInfoTbMapper.changeAuthRes(labels);
            resInfoTbMapper.batchInsertRoleRes(changeAuthBO.getRoleId(), changeAuthList);
        } else {
            //取消授权
//            resInfoTbMapper.changeCancleAuthRes(labels);
//            resInfoTbMapper.deleteRoleRes(changeAuthBO.getRoleId(), changeAuthList);
            //批量删除待处理
            for (ChangeAuthResBO changeAuthResBO : changeAuthList) {
                resInfoTbMapper.deleteRoleRes(changeAuthBO.getRoleId(), changeAuthResBO.getResId());
            }
        }
        return Result.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result isEnable(IsEnableBO isEnableBO) {
        resInfoTbMapper.isEnable(isEnableBO);
        return Result.ok();
    }

    @Override
    public Result queryOne(Integer resId) {
        return Result.ok(resInfoTbMapper.selectById(resId));
    }

    /**
     * 查询未授权的资源信息
     *
     * @param roleId
     */
    public List<ResInfoTbEntity> queryHasNotAuthrizeResources(Integer roleId) {
        return resInfoTbMapper.queryHasNotAuthrizeResources(roleId);
    }
}